home *** CD-ROM | disk | FTP | other *** search
/ PsL Monthly 1993 December / PSL Monthly Shareware CD-ROM (December 1993).iso / prgmming / dos / c / stdlib1.exe / lha / MEMORY.ASM < prev    next >
Assembly Source File  |  1990-07-10  |  24KB  |  841 lines

  1.         extrn    PSP:word
  2. stdlib        segment    para public 'slcode'
  3.         assume    cs:stdlib
  4. ;
  5. ; Memory allocation routines: MemInit, malloc, and free.
  6. ;
  7. ;
  8. ; Local variables:
  9. ;
  10. StartOfHeap    dw    ?
  11. SizeOfHeap    dw    ?
  12. FreeSpace    dw    ?
  13. ;
  14. ; Memory manager data structure:
  15. ;
  16. mmstruct    struc
  17. blksize        dw    ?
  18. bwdptr        dw    ?
  19. fwdptr        dw    ?
  20. refcnt        dw    ?
  21. freebwdptr    dw    ?        ;Only if in the free list.
  22. freefwdptr    dw    ?        ;Only if in the free list.
  23.         ends
  24. ;
  25. ; When using es and ds as pointers into the heap, the following equates
  26. ; come in handy.
  27. ;
  28. esptr        equ    word ptr es:[0]
  29. dsptr        equ    word ptr ds:[0]
  30. ;
  31. NIL        equ    0
  32. ;
  33. ;
  34. ; MemInit- Initializes the memory manager.
  35. ;
  36. ;    On entry- DX contains the number of paragraphs of memory to reserve
  37. ;          for other programs.  The default (in shell.asm) is 0.  If
  38. ;          you intend to execute other programs from the program you're
  39. ;          writing, you will have to reserve an appropriate amount of
  40. ;          space for that program.  If you attempt to reserve too
  41. ;          much space, then this code splits the available free memory
  42. ;          in half and gives half to the heap and reserves half for
  43. ;          other programs.  If this is desirable, simply set DX to
  44. ;          0ffffh before calling MemInit.
  45. ;
  46. ;    On Exit-  No error if carry is clear.  In such a case, CX contains
  47. ;          the number of paragraphs of memory actually allocated.
  48. ;          AX contains the starting segment address of the free
  49. ;          memory block.
  50. ;
  51. ;          If carry is set, then an error occurred, AX contains the
  52. ;          error code (DOS).
  53. ;
  54. ; WARNING: for this routine to work properly, the calling program has to
  55. ; declare (and initialize) a word variable by the name PSP which contains
  56. ; the program's program segment prefix value.  Furthermore, the last segment
  57. ; in the program must be "zzzzzzseg" and this guy should NOT contain any
  58. ; valid data.
  59. ;
  60.         public    sl_MemInit
  61. sl_MemInit    proc    far
  62.         push    bx
  63.         push    dx
  64.         push    es
  65. ;
  66. ; Compute program size, in paragraphs:
  67. ;
  68.         mov    ax, seg PSP
  69.         mov    es, ax
  70.         mov    bx, es:PSP
  71.         mov    es, bx
  72.         mov    ax, seg zzzzzzseg
  73.         sub    ax, bx
  74.         inc    bx            ;Safety margin
  75.         inc    bx
  76.         mov    ah, 4ah            ;Memory block resize opcode
  77.                 int    21h
  78. ;
  79. ; Now ask for a ridiculous amount of memory so we can find out how much is
  80. ; available.
  81. ;
  82.         mov    bx, 0ffffh
  83.         mov    ah, 48h            ;Alloc block opcode
  84.         int    21h
  85. ;
  86. ;
  87. ; Allocate storage for the heap.
  88. ;
  89.         cmp    bx, dx            ;See if DX is too large.
  90.         ja    GoodHeap
  91.         shr    bx, 1            ;Use half remaining space.
  92.         jmp    short SetNewAlloc
  93. ;
  94. GoodHeap:    sub    bx, dx            ;Make room for other apps.
  95. SetNewAlloc:    cmp    bx, 10h            ;Make sure there is some room.
  96.         jbe    ErrorAlloc2
  97.         mov    ah, 48h            ;Alloc block opcode
  98.         int    21h
  99.         jc    ErrorAlloc        ;Shouldn't happen, but...
  100. ;
  101. ; Okay, we've just allocated the block, now set up our own local variables
  102. ; so we can keep track of the data.
  103. ;
  104.         mov    cs:StartOfHeap, ax    ;Save pointer to memory.
  105.         mov    cs:FreeSpace, ax    ;Save pointer to 1st free blk.
  106.         mov    cs:SizeOfHeap, bx    ;Size of heap in paragraphs.
  107.         mov    es, ax            ;Init pointer to heap.
  108.                 xor    ax, ax
  109.         mov    esptr.blksize, bx    ;Size of this block (paras).
  110.         mov    esptr.bwdptr, ax    ;Back pointer is NIL.
  111.         mov    esptr.fwdptr, ax    ;Fwd pointer is NIL.
  112.         mov    esptr.refcnt, ax    ;Reference Count is zero.
  113.         mov    esptr.freebwdptr, ax    ;Free list bwd ptr is NIL.
  114.         mov    esptr.freefwdptr, ax    ;Free list fwd ptr is NIL.
  115.         mov    cx, bx            ;Return size in CX
  116.         mov    ax, cs:StartOfHeap
  117.         clc
  118.         jmp    MemInitDone
  119. ;
  120. ErrorAlloc2:    mov    ax, 8            ;Insufficient memory error.
  121. ErrorAlloc:    stc
  122. MemInitDone:    pop     es
  123.         pop    dx
  124.         pop    bx
  125.         ret
  126. sl_MemInit    endp
  127. ;
  128. ;
  129. ;
  130. ;
  131. ;============================================================================
  132. ;
  133. ;    *     *      *      *        *         *****       *****
  134. ;    **   **     * *     *        *        *     *     *     *
  135. ;    * * * *    *   *    *        *        *     *     *
  136. ;    *  *  *    *****    *        *        *     *     *
  137. ;    *     *    *   *    *      *        *     *     *
  138. ;    *     *    *   *    *        *        *     *     *     *
  139. ;    *     *    *   *    *****    *****     *****       *****
  140. ;
  141. ;============================================================================
  142. ;
  143. ;
  144. ; malloc-  On entry, CX contains a byte count.  Malloc allocates a block
  145. ;       of storage of the given size and returns a pointer to this block
  146. ;       in ES:DI.  The value in ES:DI is always normalized, so you can
  147. ;       compare pointers allocated via malloc as 32-bit values.  Note
  148. ;       that malloc always allocates memory in paragraph chunks.
  149. ;       Therefore, this routine returns the actual number of bytes of
  150. ;       memory allocated in the CX register (this may be as much as 15
  151. ;       greater than the actual number asked for).
  152. ;
  153. ;       Malloc returns carry clear if it allocated the storage without
  154. ;       error.  It returns carry set if it could not find a block large
  155. ;       enough to satisfy the request.
  156. ;
  157. ;
  158. ; Data structure for memory allocation blocks:
  159. ;
  160. ; offset:
  161. ;
  162. ;   0    Size of Blk
  163. ;   2   Back link
  164. ;   4   Fwd Link
  165. ;   6   Reference Count
  166. ;   8   Data, if this block is allocated, prev link if on free list.
  167. ;  10    Data, if this block is allocated, next link if on free list.
  168. ;
  169. ;
  170. ;
  171.         public    sl_malloc
  172. sl_malloc    proc    far
  173.         push    ax
  174.         push    si
  175.         push    ds
  176. ;
  177. ; Convert byte count to paragraph count, since we always allocate whole
  178. ; paragraphs.
  179. ;
  180.         add    cx, 8            ;We have six bytes of overhead!
  181.         rcr    cx, 1            ;Use rcr because of add above.
  182.         adc    cx, 0
  183.         shr    cx, 1
  184.         adc    cx, 0
  185.         shr    cx, 1
  186.         adc    cx, 0
  187.         shr    cx, 1
  188.         adc    cx, 0
  189. ;
  190. ; Go find a block in the free list which is large enough.
  191. ;
  192. ; Uses the following algorithm:
  193. ;
  194. ;
  195.         cmp    cs:FreeSpace, 0        ;See if no free space.
  196.         jz    MemoryFull
  197.         mov    ds, cs:FreeSpace
  198.         mov    ax, ds            ;In case first block is it.
  199. FindBlk:    cmp    cx, dsptr.blksize    ;See if blk is large enuf.
  200.         jbe    FoundBlk        ;Go for it!
  201.         mov     ax, dsptr.freefwdptr    ;Get ptr to next free block.
  202.         mov    ds, ax            ;Set up pointer.
  203.         or    ax, ax            ;See if NIL
  204.                 jnz    FindBlk            ;Repeat until NIL.
  205. ;
  206. ; If we drop down here, we've got some big problems.
  207. ;
  208. MemoryFull:    stc
  209.         pop    ds
  210.         pop    si
  211.         pop    ax
  212.         mov    es, cs:StartOfHeap    ;In case they use this ptr
  213.         mov    di, 8            ; anyway.
  214.         ret
  215. ;
  216. ; When we come down here, we've found a block large enough to satisfy the
  217. ; current memory request.  If necessary, split the block up into two
  218. ; pieces and return the unused half back to the free pool.
  219. ;
  220. FoundBlk:       jne    SplitBlock
  221. ;
  222. ;
  223. ;
  224. ;***************************************************************************
  225. ; Exact fit, remove this guy from the free list and go for it!
  226. ;***************************************************************************
  227. ;
  228. ; There are four cases to deal with if this is an exact fit:
  229. ;
  230. ;    1) The block we're allocating is the first block in the free list.
  231. ;       In this case, FreeSpace points at this block and the freebwdptr
  232. ;       entry is NIL.
  233. ;
  234. ;    2) The block we're allocating is neither the first or last in the
  235. ;       free list.
  236. ;
  237. ;    3) The block we're allocating is the last block in the free list.
  238. ;       In this case, the freefwdptr will be NIL.
  239. ;
  240. ;    4) The block is both the first and last (i.e., only) block in the
  241. ;       the free list.
  242. ;
  243. ; At this point, DS points at the block we're going to allocate.
  244. ;
  245.         mov    ax, dsptr.freefwdptr    ;Pointer to next free block.
  246.         cmp    dsptr.freebwdptr, NIL    ;First item in list?
  247.         jnz    NotFirst
  248. ;
  249. ; Case (1) and (4) drop down here.
  250. ;
  251. ; If this is the first free block in the free link list, point FreeSpace
  252. ; beyond this guy rather than going through the usual linked list stuff.
  253. ;
  254. ; AX contains a pointer to the next free block (after this one) if it exists.
  255. ; DS points at the current free block.
  256. ;
  257. ; Since we are removing the first free block, we need to update the FreeSpace
  258. ; pointer so that it points at the next free block in the free block list.
  259. ;
  260.         mov    cs:FreeSpace, ax    ;Note: AX may be NIL if case (4).
  261. ;
  262. ; See if there is another block after this one.  If not (case 4) then jump
  263. ; off to FixThisBlk.
  264. ;
  265.         or    ax, ax            ;Is there another free blk?
  266.         jz    FixThisBlk        ;If not, don't patch next adrs.
  267. ;
  268. ; Case (1), only, do